#include <commctrl.h>
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <windows.h>
#include <wininet.h>
#include "func.h"
#include "grid.h"

#define ID_BUTTON0 1
#define ID_BUTTON1 2
#define ID_BUTTON2 3

HWND CInput0, CInput1, CLabel0, CPrgbar;
char* newfile = NULL;

#define HOSTSDIR L"C:\\Windows\\System32\\drivers\\etc\\hosts"
#define HOSTURL                                                             \
  "https://raw.githubusercontent.com/googlehosts/hosts/master/hosts-files/" \
  "hosts"

void updateLocalHosts() {
  char* hostfile = ReadFileAll(HOSTSDIR);
  wchar_t* hostinfo = getHostInfo(hostfile);
  SetWindowTextW(CInput0, hostinfo);
  free(hostfile);
}

DWORD WINAPI updateRemoteHosts(LPVOID lpParam) {
  SendMessage(CPrgbar, PBM_SETMARQUEE, 1, 0);
  char* hostfile = ReadFileAll(HOSTSDIR);
  char* sha1 = getGitsha1(hostfile);
  char header[80];
  sprintf(header, "If-None-Match: \"%s\"", sha1);
  HINTERNET hInet =
      InternetOpenW(L"inetapp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
  HINTERNET hReq =
      InternetOpenUrlA(hInet, HOSTURL, header, strlen(header), 0, 0);
  if (!hReq) {
    SetWindowTextW(CLabel0, L"网络连接失败");
  } else {
    DWORD status = HttpHeaderNum(hReq, HTTP_QUERY_STATUS_CODE);
    if (status == 304) {
      SetWindowTextW(CInput1, getHostInfo(hostfile));
      SetWindowTextW(CLabel0, L"已是最新版, 无需更新");
    } else {
      DWORD contlen = HttpHeaderNum(hReq, HTTP_QUERY_CONTENT_LENGTH);
      newfile = HttpReadAll(hReq, contlen);
      SetWindowTextW(CInput1, getHostInfo(newfile));
      SetWindowTextW(CLabel0, L"需要更新, 请点更新按钮更新");
    }
  }
  InternetCloseHandle(hReq);
  InternetCloseHandle(hInet);
  free(hostfile);
  free(sha1);
  SendMessage(CPrgbar, PBM_SETMARQUEE, 0, 0);
}

void CreateControls(HWND hwnd) {
  GridSetHwnd(hwnd);
  GridLabel(0, 1, 1, L"本地版本：");
  CInput0 = GridInput(0, 2, 1, 0, ES_READONLY);
  GridButton(0, 1, 1, ID_BUTTON0, L"刷新");
  GridLabel(1, 1, 1, L"远程版本：");
  CInput1 = GridInput(1, 2, 1, 0, ES_READONLY);
  GridButton(1, 1, 1, ID_BUTTON1, L"刷新");
  CPrgbar = GridProgress(2, 4, 1, 0);
  CLabel0 = GridLabel(3, 3, 1, L"CHosts-0.1.0-2017.10.27");
  GridButton(3, 1, 1, ID_BUTTON2, L"更新");
  GridSetSysfont();
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  switch (msg) {
    case WM_CREATE:
      CreateControls(hwnd);
      updateLocalHosts();
      break;
    case WM_COMMAND: {
      WORD hParam = HIWORD(wParam);
      WORD lParam = LOWORD(wParam);
      if (hParam == BN_CLICKED) {
        if (lParam == ID_BUTTON0) updateLocalHosts();
        if (lParam == ID_BUTTON1)
          CloseHandle(CreateThread(NULL, 0, updateRemoteHosts, NULL, 0, NULL));
        if (lParam == ID_BUTTON2 && newfile) {
          SaveTextFile(HOSTSDIR, newfile);
          SetWindowTextW(CLabel0, L"已更新至最新版");
        }
      }
      break;
    }
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
  }
  return DefWindowProcW(hwnd, msg, wParam, lParam);
}

int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE h0, LPWSTR lpCmdLine,
                    int nCmdShow) {
  LPCWSTR appName = L"CHosts";
  HANDLE mu = CreateMutexW(NULL, TRUE, appName);
  if (GetLastError() == ERROR_ALREADY_EXISTS) {
    HWND exist = FindWindowW(appName, NULL);
    ShowWindow(exist, SW_RESTORE);
    return 0;
  }
  GridInitComctl();
  GridInit(24, 64, 8, 8);
  GridMainWindow(hInst, appName, WndProc, 4, 4);
  GridSetTopmost();

  MSG msg;
  while (GetMessageW(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
  }
  return (int)msg.wParam;
}